<?php
defined( 'BASEPATH' ) or exit( 'No direct script access allowed' );
class MyLog
{
    private static $_instance = null;
    private $_config = array (
            'table_name_id' => 'log_id',
            'table_name_request' => 'log_request',
            'table_name_msg' => 'log_msg',
            'flag' => 255 
    );
    private $_request_id = 0;
    private $_request = array ();
    private $_msg_list = array ();
    private $_uid = 0;
    private $_result = null;
    private $_db = null;
    private $_start_time = 0.0;
    private function __construct($config)
    {
        // 配置
        if (is_array( $config ))
        {
            foreach ( $config as $k => $v )
            {
                $k = strtolower( $k );
                if (isset( $this->_config[$k] ))
                {
                    $this->_config[$k] = $v;
                }
            }
        }
        
        // 数据库连接
        if (! class_exists( 'MyPDO', false ))
        {
            exit( 'Not found mysql driver' );
        }
        $this->_db = MyPDO::get_instance();
        
        // 通过获取数据库自增ID，得到请求ID
        // $request_id = $this->_db->sql( 'REPLACE INTO log_id() VALUES()' )->last_id();
        $this->_request_id = $this->_db->exec( 'REPLACE INTO `_' . $this->_config['table_name_id'] . '`() VALUES()' )->last_id();
        
        // 记录请求信息
        if ($this->_config['flag'] & 8)
        {
            $this->_request = array (
                    'file' => isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : isset( $_SERVER['PHP_SELF'] ) ? $_SERVER['PHP_SELF'] : null,
                    'get' => json_encode( $_GET, JSON_UNESCAPED_UNICODE ),
                    'post' => json_encode( $_POST, JSON_UNESCAPED_UNICODE ),
                    'cookie' => json_encode( $_COOKIE, JSON_UNESCAPED_UNICODE ),
                    'host' => isset( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : null,
                    'referer' => isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : null,
                    'remote' => isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : null,
                    'agent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : null,
                    'add_time' => isset( $_SERVER['REQUEST_TIME'] ) ? $_SERVER['REQUEST_TIME'] : 0,
                    'client_id' => (isset( $_COOKIE['CLIENT_ID'] ) && is_string( $_COOKIE['CLIENT_ID'] )) ? $_COOKIE['CLIENT_ID'] : null 
            );
        }
        
        // 退出时自动保存到数据库
        register_shutdown_function( array (
                $this,
                'save' 
        ) );
        
        $this->_start_time = $_SERVER['REQUEST_TIME_FLOAT'];
    }
    private function __clone()
    {
    }
    /**
     * 保证“唯一”请求ID
     *
     * @return MysqlLog
     */
    public static function get_instance($config = array())
    {
        if (! isset( self::$_instance ))
        {
            self::$_instance = new self( $config );
        }
        return self::$_instance;
    }
    function get_request_id()
    {
        return $this->_request_id;
    }
    function set_user($uid)
    {
        $this->_uid = $uid;
    }
    function set_session()
    {
        if (! isset( $this->_request['session_id'] ))
        {
            $this->_request['session_id'] = session_id();
            $this->_request['session_data'] = serialize( $_SESSION );
        }
    }
    function set_result($result)
    {
        $this->_result = $result;
    }
    /**
     * 记录消息
     * 0错误，1警告，2信息
     *
     * @param string $msg            
     * @param number $level            
     */
    function add($msg, $level = 0)
    {
        $level = ( int ) $level;
        if ($this->_config['flag'] & pow( 2, $level ))
        {
            $this->_msg_list[] = array (
                    'content' => $msg,
                    'level' => $level 
            );
        }
    }
    function save()
    {
        // 保存请求日志
        if ($this->_config['flag'] & 8)
        {
            if (isset( $this->_result ))
            {
                $this->_request['result'] = $this->_result;
            }
            else
            {
                // 通过缓冲区获取返回给客户端的结果
                for($level = ob_get_level(); $level > 1; -- $level)
                {
                    ob_end_flush();
                }
                $this->_request['result'] = ob_get_contents();
            }
            $this->_request['result_header'] = json_encode( headers_list(), JSON_UNESCAPED_UNICODE );
            
            $this->_request['id'] = $this->_request_id;
            $this->_request['uid'] = $this->_uid;
            $this->_request['runtime'] = ( int ) (1000 * (microtime( true ) - $this->_start_time));
            $this->_db->insert( $this->_config['table_name_request'], $this->_request )->execute();
        }
        
        // 保存消息日志
        foreach ( $this->_msg_list as $msg )
        {
            $msg['add_time'] = $_SERVER['REQUEST_TIME'];
            $msg['ip'] = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : null;
            $msg['request_id'] = $this->_request_id;
            $msg['uid'] = $this->_uid;
            $msg_list[] = $msg;
        }
        if (! empty( $msg_list ))
        {
            $this->_db->insert( $this->_config['table_name_msg'], $msg_list )->execute();
        }
    }
}
